CalculateMe#1 by Marcus by mario

Cel: CalculateMe#1 by Marcus^HTBTeam

Poziom: easy

Narzdzia: IDA (przyda si te windowsowski kalkulator)

Data: 14.o6.2oo4

W pliku ReadMe.txt doczonym do crackme mamy wsio elegancko wyjanione :), wic powicamy chwil na przeczytanie go i jedziemy..

Najpierw dobierzemy si do "Decoder.exe", PEiD podpowiada nam, e plik spakowany jest FSG (1.33). Moemy odpakowa go od razu za pomoc plugina lub rcznie, jak komu wygodnie ;). Ok, odpakowany plik wrzucamy do IDY i szukamy kawaka kodu odpowiedzialnego za pobieranie textu:

004010F7    push    0FFh            ; nMaxCount
004010FC    push    offset String   ; lpString
00401101    push    64h             ; nIDDlgItem
00401103    push    [ebp+hDlg]      ; hDlg
00401106    call    GetDlgItemTextA ; czyli tutaj
0040110B    cmp     eax, 0
0040110E    jz      loc_401251
00401114    mov     esi, offset String
00401119    mov     edi, offset String
0040111E    xor     edx, edx
...               ...

Nastpnie od 0040111E do 00401157 mamy procedurk, zamieniajc stringa (czyli nasz wpisany "kluczyk") na hexy, warto hex zapisana jest pod ds:String czyli w tym samym miejscu.
Dalej:

00401165    call    SetFileAttributesA
0040116A    push    0               ; hTemplateFile
0040116C    push    80h             ; dwFlagsAndAttributes
00401171    push    3               ; dwCreationDisposition
00401173    push    0               ; lpSecurityAttributes
00401175    push    0               ; dwShareMode
00401177    push    0C0000000h      ; dwDesiredAccess
0040117C    push    offset aCalculateme1_e ; lpFileName
00401181    call    CreateFileA

00401186    cmp     eax, 0FFFFFFFFh
00401189    jz      loc_40123C

0040118F    mov     ds:hFile, eax

00401194    push    0               ; lpFileSizeHigh
00401196    push    eax             ; hFile
00401197    call    GetFileSize

0040119C    mov     ds:dwMaximumSizeLow, eax

004011A1    push    0               ; lpName
004011A3    push    ds:dwMaximumSizeLow ; dwMaximumSizeLow
004011A9    push    0               ; dwMaximumSizeHigh
004011AB    push    4               ; flProtect
004011AD    push    0               ; lpFileMappingAttributes
004011AF    push    ds:hFile        ; hFile
004011B5    call    CreateFileMappingA

004011BA    mov     ds:hObject, eax

004011BF    push    0               ; dwNumberOfBytesToMap
004011C1    push    0               ; dwFileOffsetLow
004011C3    push    0               ; dwFileOffsetHigh
004011C5    push    2               ; dwDesiredAccess
004011C7    push    eax             ; hFileMappingObject
004011C8    call    MapViewOfFile

004011CD    mov     ds:lpBaseAddress, eax

Po kolei.. Sprawdzamy czy istnieje plik "CalculateMe#1.exe" i pobieramy jego uchwyt, nastpnie pobieramy wielko pliku i wrzucamy j do ds:dwMaximumSizeLow. Teraz mapujemy plik w celu odczytania i zapisania danych do niego. W kocu do eax lduje adres w pamici gdzie znajduj si dane ze zmapowanego pliku..

004011D2    xchg    eax, edx    ;teraz edx wskazuje nam adres z danymi
004011D3    pusha
004011D4    mov     edi, ds:String  ;do edi leci "kluczyk"
004011DA    mov     ecx, ds:dwMaximumSizeLow ;w ecx lduje wielko pliku

Dla przykadu, gdy nasz kluczyk jest postaci "12345678" to po zmianie na hexy i wrzuceniu do edi bedzimy mie "78563412", taa teraz chyba wszystko jasne :), wic przejdmy do najwaniejszej czci:

004011E0    xor     esi, esi
004011E2
004011E2 loc_4011E2:                ; CODE XREF: DialogFunc+1D8j
004011E2    cmp     ecx, 4
004011E5    jb      short loc_401205
004011E7    mov     eax, [esi+edx]
004011EA    add     eax, edi
004011EC    not     eax
004011EE    bswap   eax
004011F0    xor     eax, edi
004011F2    ror     eax, 2
004011F5    sub     eax, 119ABE7h
004011FA    mov     [esi+edx], eax
004011FD    add     esi, 4
00401200    sub     ecx, 4
00401203    jmp     short loc_4011E2

Tu nastpuje odkodowanie "CalculateMe#1.exe". Widzimy, e kady dword pliku jest pobierany do eax, poskrcany przy pomocy kluczyka (edi) i wrzucany w to samo miejsce.

Aby odkodowa plik musimy znale prawidowy klucz. Wiemy, e kady dziaajcy exek zaczyna si znan sygnaturk "MZ", a dokadniej od dword'a 4D5A9000 i wiemy te, e oryginalny exek "CalculateMe#1.exe" doczony do archiwum ma pierwszy dword rwny 9B51C06C, no wic teraz wystarczy sklei na szybko maego bruta, na wstpie [esi+edx] = 9B51C06C, edi to niewiadoma czyli nasz kluczyk. Na kocu [esi+edx] ma wynie 4D5A9000... Zapuszczamy b-f i mamy takie wyniki:

0370D65F    0A70D658    0B70D657    1270D650
0371D55F    0A71D558    0B71D557    1271D550
0372D45F    0A72D458    0B72D457    1272D450
0373D35F    0A73D358    0B73D357    1273D350
0374D25F    0A74D258    0B74D257    1274D250
0375D15F    0A75D158    0B75D157    1275D150
0376D05F    0A76D058    0B76D057    1276D050
0378DE5F    0A78DE58    0B78DE57    1278DE50
0379DD5F    0A79DD58    0B79DD57    1279DD50
037ADC5F    0A7ADC58    0B7ADC57    127ADC50
037BDB5F    0A7BDB58    0B7BDB57    127BDB50
037CDA5F    0A7CDA58    0B7CDA57    127CDA50
037DD95F    0A7DD958    0B7DD957    127DD950
037ED85F    0A7ED858    0B7ED857    127ED850

Pamitajmy, e po zmianie na stringa dword jest odwracany. Dla przykadu podstawmy pierwszy wynik czyli 5FD67003 (po odwrceniu). Wane, eby ZAWSZE odkodowa oryginalny plik "CalculateMe#1.exe", chyba nie trzeba tumaczy dlaczego :|

Po odkodowaniu lookamy na CalculateMe#1 pod jakim hexedytorem. Pierwszy wynik okazuje si daleki od waciwego :P, sprawdzamy drug kolumn wynikw, podstawiamy 58D6700A i znowu zagldamy pod hexedytorek. Tym razem dostrzegamy zalki :) tabeli importw (offset 154) wyglda to mniej wicej tak: KSONE862.pll  Lo_dLibnarw? ... Czyli jestemy bardzo blisko =) ja podstawiem od razu ostatniego dworda z tej samej kolumny, eby sprawdzi jak dua bdzie rnica.. A tu taka niespodzianka :). Okazuje si, e kod "58D87E0A" odkodowuje elegancko caego exeka.. Hehe poprostu kobieca intuicja :P

No teraz zabieramy si za crackmesa, exe rwnie spakowany FSG, wic po odpakowaniu wrzucamy do IDY i szukamy tego kawaka kodu:

00401121    push    0FFh
00401126    push    offset dword_4044E5
0040112B    push    64h
0040112D    push    [ebp+arg_0]
00401130    call    sub_401504      ; pobierz key1
00401135    cmp     eax, 0
00401138    jz      short loc_40115B
0040113A    push    0FFh
0040113F    push    offset dword_4045E4
00401144    push    65h
00401146    push    [ebp+arg_0]
00401149    call    sub_401504      ; pobierz key2
0040114E    cmp     eax, 0
00401151    jz      short loc_40115B
00401153    push    [ebp+arg_0]
00401156    call    sub_4011E5      ; gwna cz crackme
0040115B

Wchodzimy do call'a (sub_4011E5) a w nim widzimy typowe procedurki do obsugi duych liczb. Polecam http://www.home.no/k23/files/blacky/be_sig1.rar, jest to zbir sygnaturek do crypto-lib'w, nie trzeba tumaczy jak to uatwia nam spraw :). Znajduje si tam te biglib.sig, czyli sygnaturka do biglib'a (BigLib v.0.0.e by roy), ktra wanie zostaa wykorzystana w tym crackme. Cay call wyglda nastepujco (z pominiciem bigcreate i bigdestroy):

...             ...
00401277    push    [ebp+var_1C]
0040127A    push    0Ah
0040127C    push    offset a87123456 ; "87123456"
00401281    call    __BigIn@12
00401286    push    [ebp+var_20]
00401289    push    0Ah
0040128B    push    offset a2519424 ; "2519424"
00401290    call    __BigIn@12
00401295    push    [ebp+var_24]
00401298    push    0Ah
0040129A    push    offset a48      ; "48"
0040129F    call    __BigIn@12
004012A4    push    [ebp+var_28]
004012A7    push    0Ah
004012A9    push    offset a3630144 ; "3630144"
004012AE    call    __BigIn@12
004012B3    push    [ebp+var_2C]
004012B6    push    0Ah
004012B8    push    offset a262144  ; "262144"
004012BD    call    __BigIn@12
004012C2    push    [ebp+var_30]
004012C5    push    0Ah
004012C7    push    offset a13365   ; "13365"
004012CC    call    __BigIn@12
004012D1    push    [ebp+var_34]
004012D4    push    0Ah
004012D6    push    offset a64      ; "6"
004012DB    call    __BigIn@12
004012E0    push    [ebp+var_38]
004012E3    push    0Ah
004012E5    push    404205h     ; "4"
004012EA    call    __BigIn@12
004012EF    push    [ebp+var_4]
004012F2    push    0Ah
004012F4    push    offset dword_4044E5 ;key1
004012F9    call    __BigIn@12
004012FE    push    [ebp+var_8]
00401301    push    0Ah
00401303    push    offset dword_4045E4 ;key2
00401308    call    __BigIn@12

..czyli zwyke wypenianie big'w liczbami. Nastpnie:

0040130D    push    [ebp+var_18]
00401310    push    [ebp+var_C]
00401313    push    [ebp+var_4] ;key1
00401316    push    [ebp+var_1C]    ;87123456
00401319    call    __BigDiv@16

..var_C = 87123456 / key1

0040131E    push    [ebp+var_C]
00401321    push    [ebp+var_34]    ;6
00401324    push    [ebp+var_C]
00401327    call    __BigMul@12
0040132C    push    [ebp+var_C]
0040132F    push    [ebp+var_34]    ;6
00401332    push    [ebp+var_C]
00401335    call    __BigMul@12
0040133A    push    [ebp+var_C]
0040133D    push    [ebp+var_34]    ;6
00401340    push    [ebp+var_C]
00401343    call    __BigMul@12
00401348    push    [ebp+var_C]
0040134B    push    [ebp+var_34]    ;6
0040134E    push    [ebp+var_C]
00401351    call    __BigMul@12
00401356    push    [ebp+var_C]
00401359    push    [ebp+var_34]    ;6
0040135C    push    [ebp+var_C]
0040135F    call    __BigMul@12

..var_C = var_C * 6^5

00401364    push    [ebp+var_C]
00401367    push    [ebp+var_20]    ;2519424
0040136A    push    [ebp+var_C]
0040136D    call    __BigAdd@12

..var_C = var_C + 2519424

00401372    push    [ebp+var_18]
00401375    push    [ebp+var_C]
00401378    push    [ebp+var_8] ;key2
0040137B    push    [ebp+var_C]
0040137E    call    __BigDiv@16

..var_C = var_C / key2

00401383    push    [ebp+var_10]
00401386    push    [ebp+var_C]
00401389    call    __BigCopy@8

..var_10 = var_C

0040138E    push    [ebp+var_18]
00401391    push    [ebp+var_C]
00401394    push    [ebp+var_28]    ;3630144
00401397    push    [ebp+var_4] ;key1
0040139A    call    __BigDiv@16

..var_C = key1 / 3630144

0040139F    push    [ebp+var_C]
004013A2    push    [ebp+var_38]    ;4
004013A5    push    [ebp+var_C]
004013A8    call    __BigMul@12
004013AD    push    [ebp+var_C]
004013B0    push    [ebp+var_38]    ;4
004013B3    push    [ebp+var_C]
004013B6    call    __BigMul@12
004013BB    push    [ebp+var_C]
004013BE    push    [ebp+var_38]    ;4
004013C1    push    [ebp+var_C]
004013C4    call    __BigMul@12
004013C9    push    [ebp+var_C]
004013CC    push    [ebp+var_38]    ;4
004013CF    push    [ebp+var_C]
004013D2    call    __BigMul@12
004013D7    push    [ebp+var_C]
004013DA    push    [ebp+var_38]    ;4
004013DD    push    [ebp+var_C]
004013E0    call    __BigMul@12
004013E5    push    [ebp+var_C]
004013E8    push    [ebp+var_38]    ;4
004013EB    push    [ebp+var_C]
004013EE    call    __BigMul@12
004013F3    push    [ebp+var_C]
004013F6    push    [ebp+var_38]    ;4
004013F9    push    [ebp+var_C]
004013FC    call    __BigMul@12
00401401    push    [ebp+var_C]
00401404    push    [ebp+var_38]    ;4
00401407    push    [ebp+var_C]
0040140A    call    __BigMul@12
0040140F    push    [ebp+var_C]
00401412    push    [ebp+var_38]    ;4
00401415    push    [ebp+var_C]
00401418    call    __BigMul@12

..var_C = var_C * 4^9

0040141D    push    [ebp+var_18]
00401420    push    [ebp+var_C]
00401423    push    [ebp+var_2C]    ;262144
00401426    push    [ebp+var_C]
00401429    call    __BigDiv@16

..var_C = var_C / 262144

0040142E    push    [ebp+var_14]
00401431    push    [ebp+var_C]
00401434    call    __BigCopy@8

..var_14 = var_C

00401439    push    [ebp+var_18]
0040143C    push    [ebp+var_C]
0040143F    push    [ebp+var_30]    ;13365
00401442    push    [ebp+var_8] ;key2
00401445    call    __BigDiv@16

..var_C = key2 / 13365

0040144A    push    [ebp+var_24]
0040144D    push    [ebp+var_10]
00401450    call    __BigCompare@8
00401455    cmp     eax, 0
00401458    jnz     short loc_40147E

..czyli var_10 musi by rwne 48

0040145A    push    [ebp+var_C]
0040145D    push    [ebp+var_14]
00401460    call    __BigCompare@8  ; _BigCompare(x,x)
00401465    cmp     eax, 0
00401468    jnz     short loc_40147E

..oraz var_14 ma by rwne var_C

0040146A    push    40h
0040146C    push    offset aCalculateme1By ; "CalculateMe #1 by Marcus //
                                              HTBTeam"
00401471    push    offset aCongratulation ; "Congratulations!!! Now send me
                                              keys and"...
00401476    push    [ebp+arg_0]
00401479    call    sub_40150A

.. I jeli wszystko si zgadza to - good_boy :)

Ufff.. Troch to zamotane, teraz tylko wystarczy to poczy w logiczn cao ;) i naszym oczkom uka si dwa rwnania:

(key1 / 3630144) * 4^9 / 262144 = key2 / 13365

Oraz

[(87123456 / key1 * 6^5) + 2519424] / key2 = 48

..teraz tylko podstawiamy sobie x i y, bierzemy kartk papieru, idziemy si odla, wracamy i wyliczamy key1 z pierwszego rwnania i po podstawieniu do drugiego rwnania, adnie wszystko skracamy, kombinujemy, a wyjdzie rwnanie kwadratowe:

-key2^2 + 52488*key2 + 13365*3888 = 0

Pierw. z delty = 54432

Key2 = 53460    ^     -972

Drugi wynik jest liczb ujemn wic darujmy sobie :P. Podstawiamy 53460 pod key2 i teraz ju atwo wyliczymy key1, powinno wyj 14520576. Zapisujemy obie liczby, sprawdzamy.. I taadaaa otrzymujemy gratulacje :) Yeah!! :] Rwnania mona rozwizywa ofcoz w inny sposb, ale wyniki powinny by takie same. Kolejny pikny dzie, kolejne puknite crackme :) No i kolejna porzdna crackerska robota w wykonaniu Marcus'a (yo!) i chwaa mu za to ;)

I standardowo, jeli czego nie rozumiesz lub z jakichkolwiek innych pobudek bliej nieokrelonych, mailme  - mario_crk@poczta.fm

--
mario/mbe
mario_crk@poczta.fm